#include "DXUT.h"
#include "RenderColorBar.h"
#include "../Utility/D3D/D3DUtilityFunction.h"


CRenderColorBar::CRenderColorBar(void) : RenderTech()
{
	m_pQuadVB = NULL;
	m_pColorBarTex = NULL;
	m_pColorBarTexSR = NULL;
	m_pVertexLayout = NULL;
	m_pRenderTech = NULL;
	m_pSampleTexSR = NULL;
	m_iWidthBar = 0;	
}

CRenderColorBar::CRenderColorBar(unsigned int iWidth) : RenderTech()
{
	m_pQuadVB = NULL;
	m_pColorBarTex = NULL;
	m_pColorBarTexSR = NULL;
	m_pVertexLayout = NULL;
	m_pRenderTech = NULL;
	m_pSampleTexSR = NULL;
	m_iWidthBar = iWidth;
}

CRenderColorBar::~CRenderColorBar(void)
{
	OnD3D11DestroyDevice(NULL);
}

HRESULT CRenderColorBar::SetBarWidth(ID3D11Device* pd3dDevice, unsigned int iWidth)
{
	if(iWidth == m_iWidthBar)
		return S_OK;
	else
	{
		m_iWidthBar = iWidth;
		return CreateColorBar(pd3dDevice);
	}

}
HRESULT CRenderColorBar::CreateColorBar(ID3D11Device* pd3dDevice)
{
	HRESULT hr = S_OK;
	if (m_iWidthBar == 0)
	{
		return E_FAIL;
	}
	SAFE_RELEASE(m_pColorBarTex);

	// Create texture
	D3D11_TEXTURE1D_DESC TexDesc;
	TexDesc.Width              = m_iWidthBar;
	TexDesc.MipLevels          = 1;
	TexDesc.ArraySize          = 1;
	TexDesc.Format             = DXGI_FORMAT_R8G8B8A8_UNORM;
	TexDesc.Usage              = D3D11_USAGE_DYNAMIC;
	TexDesc.BindFlags          = D3D11_BIND_SHADER_RESOURCE;
	TexDesc.CPUAccessFlags     = D3D11_CPU_ACCESS_WRITE;
	// If they request mipmap levels, it's nice to be able to autogenerate them.
	TexDesc.MiscFlags          = 0;

	D3D11_SUBRESOURCE_DATA Initdata;
	//prepare color info
	RGBA8Bytes* pColorArr = new RGBA8Bytes[m_iWidthBar];
	float fStep = 1.0f/m_iWidthBar;
	for(unsigned int i = 0; i < m_iWidthBar; i++)
	{
		float fVal = (i+0.5f)*fStep;
		D3DXVECTOR3 color = CD3DUtilityFunction::GetColour(fVal,0.0f,1.0f);
		pColorArr[i].r = color.x * 255;
		pColorArr[i].g = color.y * 255;
		pColorArr[i].b = color.z * 255;
		pColorArr[i].a = 255;
	}
	Initdata.pSysMem = pColorArr;
	Initdata.SysMemPitch = 0;
	Initdata.SysMemSlicePitch = 0;

	V(pd3dDevice->CreateTexture1D(&TexDesc,&Initdata,&m_pColorBarTex));

	// Create the shader-resource view
	D3D11_SHADER_RESOURCE_VIEW_DESC SRDesc;
	SRDesc.Format                    = TexDesc.Format;
	SRDesc.ViewDimension             = D3D11_SRV_DIMENSION_TEXTURE1D;
	SRDesc.Texture1D.MostDetailedMip = 0;
	SRDesc.Texture1D.MipLevels       = TexDesc.MipLevels;

	SAFE_RELEASE(m_pColorBarTexSR);
	V(pd3dDevice->CreateShaderResourceView(m_pColorBarTex, &SRDesc, &m_pColorBarTexSR));

	SAFE_DELETE_ARRAY(pColorArr);
	return hr;
}

void CRenderColorBar::InitEffectsVariables()
{
	if(m_pEffect==NULL)
		return;
	m_pRenderTech = m_pEffect->GetTechniqueByName("RenderFullScreenQuad");
	m_pSampleTexSR = m_pEffect->GetVariableByName("texColorBar")->AsShaderResource();
}

void CRenderColorBar::ReloadEffectsDebug(ID3D11Device* pd3dDevice, CDirectoryUtil* pDirUtil)
{
	HRESULT hr = S_OK;
	SAFE_RELEASE(m_pEffect);

	//create effects
	TCHAR ShaderFileDir[MAX_PATH];
	enum SUBDIRECTORY subfolder = SUBDIRECTORY::SHADERSDIR;
	pDirUtil->GetAbsoluteFileFolder(L"RenderQuad.fx",subfolder, ShaderFileDir);
	hr = CD3DUtilityFunction::CreateEffectsFromFile(pd3dDevice, ShaderFileDir, NULL, "fx_5_0", &m_pEffect);	
	InitEffectsVariables();
}

HRESULT CRenderColorBar::OnD3D11CreateDevice(ID3D11Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, 
	                                         CDirectoryUtil* pDirUtil, void* pUserContext)
{
	if (m_iWidthBar == 0)
	{
#ifdef _DEBUG
		OUTPUTERRORINFO;
#endif
			return E_FAIL;
	}
	HRESULT hr = S_OK;
	V(CreateColorBar(pd3dDevice));
	//create the vertex buffer
	V(CD3DUtilityFunction::CreateScreenQuadVB(pd3dDevice,&m_pQuadVB));
	//create effects
	TCHAR ShaderFileDir[MAX_PATH];
	enum SUBDIRECTORY subfolder = SUBDIRECTORY::SHADERSDIR;
	pDirUtil->GetAbsoluteFileFolder(L"RenderQuad.fx",subfolder, ShaderFileDir);
	hr = CD3DUtilityFunction::CreateEffectsFromFile(pd3dDevice, ShaderFileDir, NULL, "fx_5_0", &m_pEffect);	
	InitEffectsVariables();
	//create vertex layout
	const D3D11_INPUT_ELEMENT_DESC layout[2] =
	{
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0,  0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT,    0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
	};
	SAFE_RELEASE(m_pVertexLayout);
	V(CD3DUtilityFunction::CreateVertexLayout(pd3dDevice,layout,ARRAYSIZE(layout), m_pRenderTech, &m_pVertexLayout));
	//set up view port
	m_iVPLeftX = floorf(pBackBufferSurfaceDesc->Width * 0.9f);
	m_iVPLeftY = floorf(pBackBufferSurfaceDesc->Height * 0.75f);
	m_iVPWidth = floorf(pBackBufferSurfaceDesc->Width * 0.02f);
	m_iVPHeight = floorf(pBackBufferSurfaceDesc->Height * 0.2f);
	return hr;
}

HRESULT CRenderColorBar::OnD3D11ResizedSwapChain( ID3D11Device* pd3dDevice, IDXGISwapChain* pSwapChain, 
	     const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, CDirectoryUtil* pDirUtil, void* pUserContext )
{
	//set up view port
	m_iVPLeftX = floorf(pBackBufferSurfaceDesc->Width * 0.9f);
	m_iVPLeftY = floorf(pBackBufferSurfaceDesc->Height * 0.75f);
	m_iVPWidth = floorf(pBackBufferSurfaceDesc->Width * 0.02f);
	m_iVPHeight = floorf(pBackBufferSurfaceDesc->Height * 0.2f);

	return S_OK;
}

void CRenderColorBar::OnD3D11DestroyDevice( void* pUserContext )
{
	SAFE_RELEASE(m_pQuadVB);
	SAFE_RELEASE(m_pVertexLayout);
	SAFE_RELEASE(m_pColorBarTex);
	SAFE_RELEASE(m_pColorBarTexSR);
}

void CRenderColorBar::OnD3D11FrameRender( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, 
	CBaseCamera* pViewCamera, CDirectoryUtil* pDirUtil, double fTime, float fElapsedTime, void* pUserContext )
{
	HRESULT hr = S_OK;

	// store off the old viewport
	UINT NumVP = 1;
	D3D11_VIEWPORT Viewports[1];
	pd3dImmediateContext->RSGetViewports(&NumVP, Viewports);

	// set the new viewport
	D3D11_VIEWPORT NewViewports[1];
	NewViewports[0].Width = m_iVPWidth;
	NewViewports[0].Height = m_iVPHeight;
	NewViewports[0].TopLeftX = m_iVPLeftX;
	NewViewports[0].TopLeftY = m_iVPLeftY;
	NewViewports[0].MinDepth = 0.0f;
	NewViewports[0].MaxDepth = 1.0f;
	pd3dImmediateContext->RSSetViewports( 1, NewViewports );

	// Set render resources
	pd3dImmediateContext->IASetInputLayout( m_pVertexLayout );
	ID3D11Buffer* pVB[1] = { m_pQuadVB };
	UINT pStride[1] = { sizeof(ScreenVertex2DTex) };
	UINT pOffset[1] = { 0 };
	pd3dImmediateContext->IASetVertexBuffers( 0, 1, pVB, pStride, pOffset );
	pd3dImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);

	//set texture
	hr = m_pSampleTexSR->SetResource(m_pColorBarTexSR);

	// Render objects here...
	// Apply the technique contained in the effect 
	D3DX11_TECHNIQUE_DESC Desc;
	m_pRenderTech->GetDesc( &Desc );

	for( UINT iPass = 0; iPass < Desc.Passes; iPass++ )
	{
		m_pRenderTech->GetPassByIndex( iPass )->Apply( 0, pd3dImmediateContext );
		pd3dImmediateContext->Draw(4,0);		
	}

	//restore view ports
	pd3dImmediateContext->RSSetViewports( NumVP, Viewports );
}


 